package com.aijk.commons.utils;


import com.aijk.commons.exception.ErrorCodeConst;
import com.aijk.commons.exception.ErrorCodeException;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Base64;

/**
 * Base64工具类
 */
public class Base64Utils {

    /**
     * 采用UTF-8编码
     */
    private static final String DEFAULT_CHARSET = "UTF-8";

    private Base64Utils() {

    }

    /**
     * Base64编码
     *
     * @param str 待编码的字符串
     * @return
     */
    public static String getBase64(String str) {
        if (str == null) {
            return str;
        }
        return Base64.getEncoder().encodeToString(str.getBytes(Charset.forName(DEFAULT_CHARSET)));
    }


    /**
     * Base64解码
     *
     * @param str 待解码的Base64字符串
     * @return
     */
    public static String getFromBase64(String str) {
        String result = null;
        if (str != null) {
            try {
                result = new String(Base64.getDecoder().decode(str), DEFAULT_CHARSET);
            } catch (UnsupportedEncodingException e) {
                throw new ErrorCodeException(ErrorCodeConst.GLOBAL_REQUEST_ERROR, e.getMessage());
            }
        }
        return result;
    }

    /**
     * Base64编码，采用默认字符集为UTF-8
     *
     * @param src 待编码的字符串
     * @return
     */
    public static String encodeToString(String src) {
        return encodeToString(src, DEFAULT_CHARSET);
    }

    /**
     * Base64编码
     *
     * @param src         待编码的字符串
     * @param charsetName 字符集名称
     * @return
     */
    public static String encodeToString(String src, String charsetName) {
        if (src == null || src.length() == 0) {
            return src;
        }
        return Base64.getEncoder().encodeToString(src.getBytes(Charset.forName(charsetName)));
    }

    /**
     * <per>
     * <p>Base64 URL 编码</p>
     * URL编码也是我们经常会面对的需求，但由于URL对反斜线“/”有特殊的意义，因此URL编码需要替换掉它，使用下划线替换。
     * </per>
     *
     * @param src 待编码的字符串
     * @return
     */
    public static String urlEncodeToString(String src) {
        return urlEncodeToString(src, DEFAULT_CHARSET);
    }

    /**
     * <per>
     * <p>Base64 URL 编码</p>
     * URL编码也是我们经常会面对的需求，但由于URL对反斜线“/”有特殊的意义，因此URL编码需要替换掉它，使用下划线替换。
     * </per>
     *
     * @param src         待编码的字符串
     * @param charsetName 字符集名称
     * @return
     */
    public static String urlEncodeToString(String src, String charsetName) {
        if (src == null) {
            return src;
        }
        return Base64.getUrlEncoder().encodeToString(src.getBytes(Charset.forName(charsetName)));
    }

    public static byte[] urlEncode(String src, String charsetName) {
        if (src == null) {
            return null;
        }
        return Base64.getUrlEncoder().encode(src.getBytes(Charset.forName(charsetName)));
    }

    /**
     * Base64解码，默认采用UTF-8字符集
     *
     * @param src base64编码字符串
     * @return
     */
    public static String urlDecodeToString(String src) {
        return urlDecode(src, DEFAULT_CHARSET);
    }

    /**
     * Base64解码
     *
     * @param src base64编码字符串
     * @return
     */
    public static String urlDecodeToString(String src, String charsetName) {
        return urlDecode(src, charsetName);
    }

    /**
     * Base64解码
     *
     * @param src         base64编码字符串
     * @param charsetName 字符集名称
     * @return
     */
    public static String urlDecode(String src, String charsetName) {
        return new String(Base64.getUrlDecoder().decode(src), Charset.forName(charsetName));
    }

    /**
     * <per>
     * <p>Base64 MIME 编码</p>
     * MIME编码器会使用<b>基本的字母数字(没有特殊符号)</b>产生BASE64输出，而且对MIME格式友好：每一行输出不超过76个字符，而且每行以“\r\n”符结束。
     * </per>
     *
     * @param src 待编码的字符串
     * @return
     */
    public static String mimeEncodeToString(String src) {
        return mimeEncodeToString(src, DEFAULT_CHARSET);
    }

    /**
     * <per>
     * <p>Base64 MIME 编码</p>
     * MIME编码器会使用<b>基本的字母数字(没有特殊符号)</b>产生BASE64输出，而且对MIME格式友好：每一行输出不超过76个字符，而且每行以“\r\n”符结束。
     * </per>
     *
     * @param src         待编码的字符串
     * @param charsetName 字符集名称
     * @return
     */
    public static String mimeEncodeToString(String src, String charsetName) {
        return Base64.getMimeEncoder().encodeToString(src.getBytes(Charset.forName(charsetName)));
    }

    public static byte[] mimeEncode(String src, String charsetName) {
        return Base64.getMimeEncoder().encode(src.getBytes(Charset.forName(charsetName)));
    }

    /**
     * Base64解码，默认采用UTF-8字符集
     *
     * @param src base64编码字符串
     * @return
     */
    public static String mimeDecodeToString(String src) {
        return mimeDecode(src, DEFAULT_CHARSET);
    }

    /**
     * Base64解码
     *
     * @param src base64编码字符串
     * @return
     */
    public static String mimeDecodeToString(String src, String charsetName) {
        return mimeDecode(src, charsetName);
    }

    /**
     * Base64解码
     *
     * @param src         base64编码字符串
     * @param charsetName 字符集名称
     * @return
     */
    public static String mimeDecode(String src, String charsetName) {
        return new String(Base64.getMimeDecoder().decode(src), Charset.forName(charsetName));
    }

    /**
     * Base64解码，默认采用UTF-8字符集
     *
     * @param src base64编码字符串
     * @return
     */
    public static String decodeToString(String src) {
        return decode(src, DEFAULT_CHARSET);
    }

    /**
     * Base64解码
     *
     * @param src base64编码字符串
     * @return
     */
    public static String decodeToString(String src, String charsetName) {
        return decode(src, charsetName);
    }

    /**
     * Base64解码
     *
     * @param src         base64编码字符串
     * @param charsetName 字符集名称
     * @return
     */
    public static String decode(String src, String charsetName) {
        return new String(Base64.getDecoder().decode(src), Charset.forName(charsetName));
    }

    /**
     * Base64编码，采用默认字符集为UTF-8
     *
     * @param src 待编码的字符串
     * @return
     */
    public static byte[] encode(String src) {
        return encode(src, DEFAULT_CHARSET);
    }

    /**
     * Base64编码
     *
     * @param src         待编码的字符串
     * @param charsetName 字符集名称
     * @return
     */
    public static byte[] encode(String src, String charsetName) {
        return Base64.getEncoder().encode(src.getBytes(Charset.forName(charsetName)));
    }
}
